package no.ntnu.fp.utils;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import no.ntnu.fp.exceptions.XMLParsingException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public final class XmlParser {
	private final static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	private final static TransformerFactory trf = TransformerFactory.newInstance();
	private final static ThreadLocal<Transformer> tr = new ThreadLocal<Transformer>(){
		@Override
		protected Transformer initialValue(){
			try {
				return trf.newTransformer();
			} catch (TransformerConfigurationException e) {
				throw new IllegalStateException("TransformerFactory is not correctly configured", e);
			}
		}
	};
	private final static ThreadLocal<DocumentBuilder> documentBuilder = 
		new ThreadLocal<DocumentBuilder>() {
			@Override
			protected DocumentBuilder initialValue() {
				try {
					return factory.newDocumentBuilder();
				} catch (ParserConfigurationException ex) {
					throw new IllegalStateException("DocumentBuilderFactory is not correctly configured", ex);
				}
			}
			
		};


	public static DocumentBuilder getThreadLocalDocumentBuilder() {
		return documentBuilder.get();
	}
	public static Transformer getThreadLocalTransformer(){
		return tr.get();
	}
	public static String getTextValue(Element element, String tagName){
		String text = ((Element)element.getElementsByTagName(tagName).item(0)).getFirstChild().getNodeValue();
		return "null".equals(text) ? null : text;
	}
	public static Element createElementWithValue(Document dom, String name, String value){
		Element element = dom.createElement(name);
		element.appendChild(dom.createTextNode(value == null || "".equals(value) ? "null" : value));
		return element; 
	}
	public static Document parseXmlString(String xml){
		InputSource is = new InputSource();
        is.setCharacterStream(new StringReader(xml));
        Document dom = null;
		try {
			dom = XmlParser.getThreadLocalDocumentBuilder().parse(is);
		} catch (SAXException e) {
			throw new XMLParsingException(xml);
		} catch (IOException e) {
			throw new XMLParsingException(xml);
		}
		return dom;
	}
	public static String convertXmlToString(Element rootElement){
		StreamResult result = new StreamResult(new StringWriter());
		DOMSource source = new DOMSource(rootElement);
		try {
			getThreadLocalTransformer().transform(source, result);
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result.getWriter().toString();
	}
		
	private XmlParser() { }
}
